home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 235 / Issue 235 - September 2007 - DPCS0907DVD.ISO / Microsoft / Expression Blend / Blend.en.msi / Sparkle.AStudio.FlipBook.cs.en < prev    next >
Encoding:
Text (UTF-16)  |  2007-03-19  |  31.7 KB  |  487 lines

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.ComponentModel;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Ink;
  8. using System.Windows.Threading;
  9. using System.IO;
  10. using System.Windows.Media;
  11.  
  12. namespace UntitledProject1
  13. {
  14.     public enum RepeatMode
  15.     {
  16.         Once,
  17.         Loop,
  18.         Bounce
  19.     }
  20.  
  21.     /// <summary>
  22.     /// INotifyPropertyChanged allows that properties of the Class InkPen
  23.     /// participate as source in data bindings.
  24.     /// </summary>
  25.     public class FlipBook : INotifyPropertyChanged
  26.     {
  27.         /// <summary>
  28.         /// INotifyPropertyChanged requires a property called PropertyChanged.
  29.         /// </summary>
  30.         public event PropertyChangedEventHandler PropertyChanged;
  31.  
  32.         // Empty content to be returned, in case the frame index is out of range.
  33.         private static StrokeCollection EmptyStrokeCollection = new StrokeCollection();
  34.  
  35.         // There are three options for repeatMode:
  36.         // Once - Plays the animations one time.
  37.         // Loop - Play in a infinite loop.
  38.         // Bounce - Plays and reverses the animation in an infinite loop.
  39.         private RepeatMode repeatMode = RepeatMode.Loop;
  40.  
  41.         // Timer that controls the player.
  42.         private DispatcherTimer timer = null;
  43.  
  44.         // Direction of the animation: 1 = play, 0 = paused, -1 = reverse.
  45.         private int playDirection = 0;
  46.  
  47.         private ObservableCollection<StrokeCollection> frames = new ObservableCollection<StrokeCollection>();
  48.         private int currentIndex = 0;
  49.         private int framesPerSecond = 10;
  50.  
  51.         #region Initialization
  52.  
  53.         public FlipBook()
  54.         {
  55.             Setup();
  56.         }
  57.  
  58.         public FlipBook(int frameCount)
  59.         {
  60.             if (frameCount < 1)
  61.             {
  62.                 frameCount = 1;
  63.             }
  64.             for (int i = 0; i < frameCount; i++)
  65.             {
  66.                 this.frames.Add(new StrokeCollection());
  67.             }
  68.             Setup();
  69.         }
  70.  
  71.         public void Setup()
  72.         {
  73.             // DelegateCommand allows drag & drop of commands to controls as
  74.             // a CLR Object Data Source under Data in the Project Panel.
  75.             playCommand = new DelegateCommand(delegate() { Play(); });
  76.             pauseCommand = new DelegateCommand(delegate() { Pause(); });
  77.             newCommand = new DelegateCommand(delegate() { Clear(); });
  78.             newFrameCommand = new DelegateCommand(delegate() { CreateNewFrame(); });
  79.             cloneFrameCommand = new DelegateCommand(delegate() { CloneCurrentFrame(); });
  80.             removeFrameCommand = new DelegateCommand(delegate() { RemoveCurrentFrame(); });
  81.             nextFrameCommand = new DelegateCommand(delegate() { NextFrame(); });
  82.             previousFrameCommand = new DelegateCommand(delegate() { PreviousFrame(); });
  83.             firstFrameCommand = new DelegateCommand(delegate() { FirstFrame(); });
  84.             lastFrameCommand = new DelegateCommand(delegate() { LastFrame(); });
  85.  
  86.             // Initializes Drawing Attributes
  87.             drawAtt = new DrawingAttributes();
  88.             drawAtt.FitToCurve = true;
  89.             drawAtt.Color = Colors.Black;
  90.             w = 9;
  91.             drawAtt.Width = w;
  92.             drawAtt.Height = w;
  93.  
  94.             // Register the attributes to raise an event when the property changes.
  95.             OnPropertyChanged("InkColor");
  96.             OnPropertyChanged("InkWidth");
  97.             OnPropertyChanged("InkAttributes");
  98.  
  99.             // Creates the first empty frame.
  100.             CreateNewFrame();
  101.         }
  102.  
  103.         #endregion
  104.  
  105.         #region Attributes
  106.  
  107.         public ICollection<StrokeCollection> Frames
  108.         {
  109.             get { return this.frames; }
  110.         }
  111.  
  112.         public int CurrentIndex
  113.         {
  114.             get { return this.currentIndex; }
  115.             set
  116.             {
  117.                 if (value >= this.frames.Count)
  118.                 {
  119.                     value = this.frames.Count - 1;
  120.                 }
  121.                 else if (value < 0)
  122.                 {
  123.                     value = 0;
  124.                 }
  125.                 this.currentIndex = value;
  126.  
  127.                 // Sends notification that the following properties have changed.
  128.                 this.OnPropertyChanged("CurrentIndex");
  129.                 this.OnPropertyChanged("CurrentFrame");
  130.                 this.OnPropertyChanged("PreviousFrame1");
  131.                 this.OnPropertyChanged("PreviousFrame2");
  132.                 this.OnPropertyChanged("PreviousFrame3");
  133.             }
  134.         }
  135.  
  136.         public StrokeCollection CurrentFrame
  137.         {
  138.             get
  139.             {
  140.                 if (this.currentIndex >= 0 && this.currentIndex < this.frames.Count)
  141.                 {
  142.                     return this.frames[this.currentIndex];
  143.                 }
  144.                 return EmptyStrokeCollection;
  145.             }
  146.         }
  147.  
  148.         public StrokeCollection PreviousFrame1
  149.         {
  150.             get
  151.             {
  152.                 int index = this.currentIndex - 1;
  153.                 if (index >= 0 && index < this.frames.Count)
  154.                 {
  155.                     return this.frames[index];
  156.                 }
  157.                 return EmptyStrokeCollection; 
  158.             }
  159.         }
  160.  
  161.         public StrokeCollection PreviousFrame2
  162.         {
  163.             get
  164.             {
  165.                 int index = this.currentIndex - 2;
  166.                 if (index >= 0 && index < this.frames.Count)
  167.                 {
  168.                     return this.frames[index];
  169.                 }
  170.                 return EmptyStrokeCollection; 
  171.             }
  172.         }
  173.  
  174.         public StrokeCollection PreviousFrame3
  175.         {
  176.             get
  177.             {
  178.                 int index = this.currentIndex - 3;
  179.                 if (index >= 0 && index < this.frames.Count)
  180.                 {
  181.                     return this.frames[index];
  182.                 }
  183.                 return EmptyStrokeCollection; 
  184.             }
  185.         }
  186.  
  187.         public RepeatMode RepeatMode
  188.         {
  189.             get { return this.repeatMode; }
  190.             set
  191.             {
  192.                 if (this.repeatMode != value)
  193.                 {
  194.                     this.repeatMode = value;
  195.                     this.OnPropertyChanged("RepeatMode");
  196.  
  197.                     if (this.playDirection == -1 && value != RepeatMode.Bounce)
  198.                     {
  199.                         this.playDirection = 1;
  200.                     }
  201.                 }
  202.             }
  203.         }
  204.  
  205.         private Color color;
  206.  
  207.         public Color InkColor
  208.         {
  209.             get { return color; }
  210.             set { color = value; OnPropertyChanged("InkColor"); UpdateAtt(); }
  211.         }
  212.  
  213.         private double w;
  214.  
  215.         public double InkWidth
  216.         {
  217.             get { return w; }
  218.             set { w = value; OnPropertyChanged("InkWidth"); UpdateAtt(); }
  219.         }
  220.  
  221.         private DrawingAttributes drawAtt;
  222.  
  223.         public DrawingAttributes InkAttributes
  224.         {
  225.             get { return drawAtt; }
  226.         }
  227.  
  228.         public int FramesPerSecond
  229.         {
  230.             get { return this.framesPerSecond; }
  231.             set
  232.             {
  233.                 if (this.framesPerSecond != value)
  234.                 {
  235.                     this.framesPerSecond = value;
  236.                     if (this.timer != null)
  237.                     {
  238.                         this.timer.Interval = TimeSpan.FromMilliseconds(1000 / this.framesPerSecond);
  239.                     }
  240.                     this.OnPropertyChanged("FramesPerSecond");
  241.                 }
  242.             }
  243.         }
  244.  
  245.         public bool IsPlaying
  246.         {
  247.             get { return this.timer != null; }
  248.             set
  249.             {
  250.                 if (this.IsPlaying != value)
  251.                 {
  252.                     if (value)
  253.                     {
  254.                         this.Play();
  255.                     }
  256.                     else
  257.                     {
  258.                         this.Pause();
  259.                     }
  260.                 }
  261.             }
  262.         }
  263.  
  264.         #endregion
  265.  
  266.         #region Frames
  267.  
  268.         public void CreateNewFrame()
  269.         {
  270.             this.frames.Add(new StrokeCollection());
  271.             this.CurrentIndex = this.frames.Count - 1;
  272.         }
  273.  
  274.         public void CloneCurrentFrame()
  275.         {
  276.             this.frames.Add(this.CurrentFrame.Clone());
  277.             this.CurrentIndex = this.frames.Count - 1;
  278.         }
  279.  
  280.         public void RemoveCurrentFrame()
  281.         {
  282.             if (this.frames.Count > 1)
  283.             {
  284.                 this.CurrentFrame.Clear();
  285.                 this.frames.Remove(this.CurrentFrame);
  286.             }
  287.             else
  288.             {
  289.                 this.CurrentFrame.Clear();
  290.                 this.CurrentIndex = 0;
  291.             }
  292.         }
  293.  
  294.         public void Play()
  295.         {
  296.             if (!this.IsPlaying)
  297.             {
  298.                 this.playDirection = 1;
  299.                 TimeSpan timeSpan = TimeSpan.FromMilliseconds(1000 / this.framesPerSecond);
  300.                 this.timer = new DispatcherTimer(timeSpan, DispatcherPriority.Normal, new EventHandler(this.PlayNextFrame), Dispatcher.CurrentDispatcher);
  301.                 this.timer.Start();
  302.                 this.OnPropertyChanged("IsPlaying");
  303.             }
  304.             else
  305.             {
  306.                 Pause();
  307.             }
  308.         }
  309.  
  310.         public void Pause()
  311.         {
  312.             if (this.IsPlaying)
  313.             {
  314.                 this.playDirection = 0;
  315.                 this.timer.Stop();
  316.                 this.timer = null;
  317.  
  318.                 this.OnPropertyChanged("IsPlaying");
  319.             }
  320.         }
  321.  
  322.         private void PlayNextFrame(object sender, EventArgs e)
  323.         {
  324.             if (this.playDirection == 1 && this.currentIndex == this.frames.Count - 1)
  325.             {
  326.                 // When the player reaches the end of the animation, check what is the current repeatMode option.
  327.                 switch (this.repeatMode)
  328.                 {
  329.                     case RepeatMode.Once:
  330.                         // Pause.
  331.                         this.Pause();
  332.                         break;
  333.                     case RepeatMode.Loop:
  334.                         // Restart at the first frame.
  335.                         this.currentIndex = -1;
  336.                         break;
  337.                     case RepeatMode.Bounce:
  338.                         // Reverse direction.
  339.                         this.playDirection = -1;
  340.                         break;
  341.                 }
  342.             }
  343.             else if (this.playDirection == -1 && this.currentIndex == 0)
  344.             {
  345.                 if (this.repeatMode == RepeatMode.Bounce)
  346.                 {
  347.                     this.playDirection = 1;
  348.                 }
  349.                 else
  350.                 {
  351.                     this.Pause();
  352.                 }
  353.             }
  354.             this.CurrentIndex += this.playDirection;
  355.         }
  356.  
  357.         public void Clear()
  358.         {
  359.             this.Pause();
  360.             this.frames = new ObservableCollection<StrokeCollection>();
  361.             this.frames.Add(new StrokeCollection());
  362.             this.currentIndex = 0;
  363.             this.OnAllPropertiesChanged();
  364.         }
  365.  
  366.         public void NextFrame() { this.CurrentIndex++; }
  367.         public void PreviousFrame() { this.CurrentIndex--; }
  368.         public void FirstFrame() { this.CurrentIndex = 0; }
  369.         public void LastFrame() { this.CurrentIndex = this.Frames.Count - 1; }
  370.  
  371.         #endregion
  372.  
  373.         #region File
  374.  
  375.         /// <summary>
  376.         /// Saves the animation as a collection of Strokes.
  377.         /// The method StrokeCollection.Save allows saving stroke binary data. 
  378.         /// </summary>
  379.         public void Save(string path)
  380.         {
  381.             FileStream writer = new FileStream(path, FileMode.Create);
  382.             writer.WriteByte((byte)this.repeatMode);
  383.             writer.WriteByte((byte)this.framesPerSecond);
  384.             foreach (StrokeCollection collection in this.Frames)
  385.             {
  386.                 collection.Save(writer);
  387.             }
  388.             writer.Close();
  389.         }
  390.  
  391.         public void Load(string path)
  392.         {
  393.             this.Pause();
  394.             FileStream reader = new FileStream(path, FileMode.Open, FileAccess.Read);
  395.             RepeatMode newRepeatMode = (RepeatMode)reader.ReadByte();
  396.             int newFramesPerSecond = reader.ReadByte();
  397.             ObservableCollection<StrokeCollection> newFrames = new ObservableCollection<StrokeCollection>();
  398.             while (reader.Position < reader.Length)
  399.             {
  400.                 newFrames.Add(new StrokeCollection(reader));
  401.             }
  402.             reader.Close();
  403.  
  404.             // Only replace the current animation if we successfully read the whole file.
  405.             this.repeatMode = newRepeatMode;
  406.             this.framesPerSecond = newFramesPerSecond;
  407.             this.frames = newFrames;
  408.             this.currentIndex = 0;
  409.             this.OnAllPropertiesChanged();
  410.         }
  411.  
  412.         #endregion
  413.  
  414.         #region Property Change
  415.  
  416.         /// <summary>
  417.         /// Fires the event for the property when it changes.
  418.         /// </summary>
  419.         private void OnPropertyChanged(string propertyName)
  420.         {
  421.             if (this.PropertyChanged != null)
  422.             {
  423.                 // In order to INotifyPropertyChanged to work it is necessary
  424.                 // that the property fires the event whenever it changes.
  425.                 this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  426.             }
  427.         }
  428.  
  429.         private void OnAllPropertiesChanged()
  430.         {
  431.             this.OnPropertyChanged("Frames");
  432.             this.OnPropertyChanged("CurrentIndex");
  433.             this.OnPropertyChanged("CurrentFrame");
  434.             this.OnPropertyChanged("PreviousFrame1");
  435.             this.OnPropertyChanged("PreviousFrame2");
  436.             this.OnPropertyChanged("PreviousFrame3");
  437.             this.OnPropertyChanged("RepeatMode");
  438.             this.OnPropertyChanged("FramesPerSecond");
  439.             this.OnPropertyChanged("InkColor");
  440.             this.OnPropertyChanged("InkWidth");
  441.             this.OnPropertyChanged("InkAttributes");
  442.         }
  443.  
  444.         /// <summary>
  445.         /// Updates the Pen attributes
  446.         /// </summary>
  447.         private void UpdateAtt()
  448.         {
  449.             drawAtt.Color = color;
  450.             drawAtt.Width = w;
  451.             drawAtt.Height = w;
  452.             OnPropertyChanged("InkAttributes");
  453.         }
  454.  
  455.         #endregion
  456.  
  457.         #region Delegate Commands
  458.  
  459.         private DelegateCommand playCommand;
  460.         private DelegateCommand pauseCommand;
  461.         private DelegateCommand newCommand;
  462.         private DelegateCommand newFrameCommand;
  463.         private DelegateCommand cloneFrameCommand;
  464.         private DelegateCommand removeFrameCommand;
  465.         private DelegateCommand nextFrameCommand;
  466.         private DelegateCommand previousFrameCommand;
  467.         private DelegateCommand firstFrameCommand;
  468.         private DelegateCommand lastFrameCommand;
  469.  
  470.  
  471.         public DelegateCommand PlayCommand { get { return playCommand; } }
  472.         public DelegateCommand PauseCommand { get { return pauseCommand; } }
  473.         public DelegateCommand NewCommand { get { return newCommand; } }
  474.         public DelegateCommand NewFrameCommand { get { return newFrameCommand; } }
  475.         public DelegateCommand CloneFrameCommand { get { return cloneFrameCommand; } }
  476.         public DelegateCommand RemoveFrameCommand { get { return removeFrameCommand; } }
  477.         public DelegateCommand NextFrameCommand { get { return nextFrameCommand; } }
  478.         public DelegateCommand PreviousFrameCommand { get { return previousFrameCommand; } }
  479.         public DelegateCommand FirstFrameCommand { get { return firstFrameCommand; } }
  480.         public DelegateCommand LastFrameCommand { get { return lastFrameCommand; } }
  481.  
  482.         #endregion
  483.  
  484.     }
  485.  
  486. }
  487.